package com.boot.noRepeatSubmitAop;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * TODO
 *
 * @Project: springboot_my
 * @Package: com.boot.noRepeatSubmitAop
 * @CreateTime: 2024-01-11  13:33
 * @Author: meikq
 * @Version: 1.0
 */
@Component
@Configuration
public class RedisLock {

    @Resource
    private RedisTemplate redisTemplate;

    private static final String PREFIXKEY = "redis_lock:";

    private static final long LockExpireTime = 30L;
    private static final Long RELEASE_SUCCESS = 1L;
    @Autowired
    @Lazy
    private DefaultRedisScript<Long> redisScript;

    public RedisLock() {
    }

    public boolean lock(String key, String value) {
        return this.redisTemplate.opsForValue().setIfAbsent("redis_lock:" + key, value, 30L, TimeUnit.SECONDS);
    }

    public boolean lock(String key, String value, long autoExpireTime) {
        return this.redisTemplate.opsForValue().setIfAbsent("redis_lock:" + key, value, autoExpireTime, TimeUnit.SECONDS);
    }

    public boolean unlock(String key, String value) {
        Long result = (Long)this.redisTemplate.execute(this.redisScript, Arrays.asList("redis_lock:" + key, "\"" + value + "\""), new Object[0]);
        return RELEASE_SUCCESS.equals(result);
    }

    @Bean
    public DefaultRedisScript<Long> defaultRedisScript() {
        DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript();
        defaultRedisScript.setResultType(Long.class);
        defaultRedisScript.setScriptText("if redis.call('get', KEYS[1]) == KEYS[2] then return redis.call('del', KEYS[1]) else return 0 end");
        return defaultRedisScript;
    }
}
